import 'dart:io';
import 'package:dio/dio.dart';

class AppException implements Exception {
  AppException([this._message, this._code]);

  final String? _message;
  final int? _code;

  String get message => _message ?? runtimeType.toString();
  int get code => _code ?? -1;

  @override
  String toString() {
    return 'code:$code--message=$message';
  }

  factory AppException.obtainFromMessage(String? error) {
    return UnknowException(error);
  }

  factory AppException.obtainFromException(Exception error) {
    if (error is DioError) {
      switch (error.type) {
        case DioErrorType.other:
          if (error.error is SocketException) {
            // SocketException: Failed host lookup: '***'
            // (OS Error: No address associated with hostname, errno = 7)
            return NetworkException(error.message);
          } else {
            return UnknowException(error.message);
          }
        case DioErrorType.connectTimeout:
        case DioErrorType.receiveTimeout:
        case DioErrorType.sendTimeout:
          return NetworkException(error.message);
        case DioErrorType.response:
          if (error.response?.statusCode == 401) {
            return UnauthorizedException(
                error.response?.statusMessage, error.response?.statusCode);
          } else {
            return HttpException(
                error.response?.statusMessage, error.response?.statusCode);
          }
        case DioErrorType.cancel:
          return CancelException(error.message);
        default:
          return FetchDataException(error.message);
      }
    } else {
      return FetchDataException(error.toString());
    }
  }
}

class HttpException extends AppException {
  HttpException(String? message, int? code) : super(message, code);
}

class FetchDataException extends AppException {
  FetchDataException(String message) : super(message);
}

class UnknowException extends AppException {
  UnknowException(String? message) : super(message);
}

class CancelException extends AppException {
  CancelException(String message) : super(message);
}

class NetworkException extends AppException {
  NetworkException(String message) : super(message);
}

class UnauthorizedException extends AppException {
  UnauthorizedException(String? message, int? code) : super(message, code);
}
